package main

//绑定参数
import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

//绑定参数之ShouldBind   func (*gin.Context).ShouldBind(obj interface{}) error
/*
	ShouldBind 支持绑定 urlencoded form 和 multipart form。

	如果是 `GET` 请求，只使用 `Form` 绑定引擎（`query`）。

	如果是 `POST` 请求，首先检查 `content-type` 是否为 `JSON` 或 `XML`，然后再使用 `Form`（`form-data`）。
*/
func main() {
	r := gin.Default()
	var user user
	//绑定到结构体   /user?username=fmx&age=19"  GET请求
	r.POST("/user", func(c *gin.Context) {
		if err := c.ShouldBind(&user); err != nil {
			c.String(http.StatusBadRequest, "err:%v", err)
			return
		}
		c.JSON(http.StatusOK, user)
	})
	//curl -H "Content-Type:application/json" -X POST "http://localhost:8081/user" -d "{\"username\":\"fmx\",\"age\":22}"  POST请求JSON格式时
	// {"username":"fmx","age":22}

	//
	//绑定到嵌套结构体  /demo?username=fmx&age=19&score=100" GET请求
	student := student{}
	r.POST("/demo", func(c *gin.Context) {
		if err := c.ShouldBind(&student); err != nil {
			c.String(http.StatusBadRequest, "err:%v", err)
			return
		}
		c.JSON(http.StatusOK, student)
	})
	//curl -H "Content-Type:application/json" -X POST "http://localhost:8081/demo" -d "{\"username\":\"fmx\",\"age\":22,\"score\":100}"  POST请求JSON格式时
	// {"UserInfo":{"username":"","age":0},"score":100}

	/*



	 */
	//绑定参数之ShouldBindJSON   func (*gin.Context).ShouldBindJSON(obj interface{}) error

	r.POST("/user1", func(c *gin.Context) {
		if err := c.ShouldBindJSON(&user); err != nil {
			c.String(http.StatusBadRequest, "err : %v", err)
			return
		}
		c.JSON(http.StatusOK, user)
	})
	//curl -H "Content-Type:application/json" -X POST "http://localhost:8081/user1" -d "{\"username\":\"fmx\",\"age\":22}"
	//{"username":"fmx","age":22}
	/*

	 */
	//绑定参数之ShouldBindXML/ShouldBindQuery/ShouldBindYAML与ShouldBindJSON类似，具体看官方文档

	//绑定参数之ShouldBindWith  ————  func (*gin.Context).ShouldBindWith(obj interface{}, b binding.Binding) error
	//ShouldBindWith 使用指定的绑定引擎，绑定传递过来的结构体指针。
	r.POST("/user2", func(c *gin.Context) {
		if err := c.ShouldBindWith(&user, binding.JSON); err != nil { //Post的方式，并指明绑定引擎
			c.String(http.StatusBadRequest, "err : %v", err)
			return
		}
		c.JSON(http.StatusOK, user)
	})
	/*	curl -H "Content-Type:application/json" -X POST "http://localhost:8081/user2" -d "{\"username\":\"fmx\",\"age\":22}"
		{"username":"fmx","age":22}
	*/

	//绑定参数之ShouldBindUri ———— func (*gin.Context).ShouldBindUri(obj interface{}) error
	r.GET("/user3/:username/:age", func(c *gin.Context) {
		if err := c.ShouldBindUri(&user); err != nil {
			c.String(http.StatusBadRequest, "err : %v", err)
			return
		}
		c.JSON(http.StatusOK, user)
	})
	//curl -X GET "http://localhost:8081/user3/fangmiaoxuan/22"    ————GET方式请求，有点像RestFul风格
	// {"username":"fangmiaoxuan","age":22}
	/*

	 */

	r.Run(":8081")
}

type user struct {
	Name string `form:"username" json:"username" xml:"username" uri:"username"`
	Age  int    `form:"age" json:"age" xml:"age" uri:"age"`
}

type student struct {
	UserInfo user `form:"userinfo"`
	Score    int  `form:"score" json:"score" xml:"score" uri:"score"`
}
